package game;

import game.log.Logger;
import game.maze.Maze;
import game.server.Server;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import shared.PlayerColours;
import shared.Tiles;
import shared.io.game.GameState;
import shared.io.game.Player;
import shared.io.game.Room;
import shared.io.startup.PlayerStartup;

public class Game {

   private static final int PLAYERS = 2;
   private static final int TORCH_DISTANCE = 5;
   
   public static void main(String[] args) {
      Logger.init();
      Logger.write("Starting server and creating game");
      new Server(new Game(PLAYERS, TORCH_DISTANCE));
   }
   
   private List<Player> players;
   private Maze maze;
   private int maxPlayers;
   private int gameStateIndex = 0;
   private int torchDistance;
   
   /**
    * Main game class
    */
   public Game(int playerCount, int torchDistance) {
      maxPlayers = playerCount;
      this.torchDistance = torchDistance;
      this.players = new ArrayList<Player>(playerCount);
      maze = new Maze(playerCount, torchDistance, this);
   }
   
   /**
    * Adds and creates a player to the game.
    */
   public synchronized Player addPlayer(PlayerStartup playerStartup) {
      int color = 0;
      for (int c : PlayerColours.COLORS) {
         boolean isUsed = false;
         for (Player p : players) {
            if (c == p.getPlayerColor()) {
               isUsed = true;
            }
         }
         if (isUsed == false) {
            color = c;
            break;
         }
      }
      Player player = new Player(playerStartup.getName(), color);
      player.setLoc(maze.getPlayerStartLoc());
      players.add(player);
      return player;
   }
   
   /**
    * Checks if the player is already in game.
    */
   public synchronized boolean containsPlayer(Player player) {
      for (Player p : players) {
         if (p.equals(player)) {
            return true;
         }
      }
      return false;
   }

   public Maze getMaze() {
      return maze;
   }

   public synchronized List<Player> getPlayers() {
      return players;
   }
   
   public List<Room> getRooms() {
      return maze.getVisibleRooms(players, torchDistance);
   }
   
   public Point setPlayerLocation(Player player, Point point) {
      if (maze.getRoom(point).getTile() == Tiles.WALL) {
         return null;
      }
      for (Player p : players) {
         if (p.equals(player)) {
            p.setLoc(point);
            break;
         }
      }
      return point;
   }
   
   public GameState getGameState() {
      gameStateIndex++;
      return new GameState(getPlayers(), gameStateIndex);
   }

   public int getMaxPlayers() {
      return maxPlayers;
   }
   
   public boolean isExit(Point p) {
      return (p.equals(maze.getExit()));
   }

   public List<Room> getAllRooms() {
      return maze.getAllRooms();
   }

   public boolean isFull() {
      return (players.size() >= maxPlayers);
   }

   public void newGame() {
      maze = new Maze(maxPlayers, torchDistance, this);
      for (Player player : players) {
         player.setLoc(maze.getPlayerStartLoc());
      }
   }
   
}
